package com.linjiahao.nettyBus.server;

import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.linjiahao.commonUtil.base.SpringContextUtil;
import com.linjiahao.nettyBus.handler.NettyServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;

import java.net.InetAddress;

/**
 * @ClassName NettyServer
 * @Description: netty服务配置
 * @Author linjiahao
 * @Date 23/12/2021
 **/
@Configuration
@Slf4j
public class NettyServer implements ApplicationListener<ApplicationStartedEvent> {

    @Value("${netty.port}")
    private int port;

    @Value("${netty.name}")
    private String name;

    @Value("${spring.cloud.nacos.discovery.server-addr}")
    private String nacosServer;

    private EventLoopGroup bossGroup = null;
    private EventLoopGroup workerGroup = null;


    @Override
    public void onApplicationEvent(@NonNull ApplicationStartedEvent applicationStartedEvent) {
        start();
    }

    public void start() {
        bossGroup = new NioEventLoopGroup(2);
        workerGroup  = new NioEventLoopGroup(6);
        ServerBootstrap bootstrap  = new ServerBootstrap();
        bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
        bootstrap.group(bossGroup,workerGroup )
                .channel(NioServerSocketChannel.class)
                .localAddress(this.port)
                //保持连接数
                .option(ChannelOption.SO_BACKLOG, 600)
                //有数据立即发送
                .option(ChannelOption.TCP_NODELAY, true)
                //保持连接
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                //处理新连接,按照tcp和websocket进行区分
                .childHandler(new NettyServerInitializer());
        ChannelFuture channelFuture  = bootstrap.bind().syncUninterruptibly().addListener(future -> {
            NamingService namingService = NamingFactory.createNamingService(nacosServer);
            //将服务注册到注册中心
            InetAddress address = InetAddress.getLocalHost();
            namingService.registerInstance(name, address.getHostAddress(), Integer.valueOf(port));
            log.info(name + "注册nacos成功");
            log.info(NettyServer.class + "已启动，正在监听："+this.port);

        });
        channelFuture.channel().closeFuture().addListener(future -> {
            destroy();
        });

    }

    public void destroy() {
        log.info(NettyServer.class +"服务stop");
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

}
